/* getmem.c - getmem */

#include <conf.h>
#include <kernel.h>
#include <mem.h>
#include <stdio.h>

/*------------------------------------------------------------------------
 * getmem  --  allocate heap storage, returning lowest WORD address
 *------------------------------------------------------------------------
 */
WORD *getmem(unsigned nbytes/* asking to allocate nbtyes */ )
{
	STATWORD ps;    
	struct	mblock	*p, *q, *leftover;

	disable(ps); //disables interrupts


	if (nbytes==0 || memlist.mnext== (struct mblock *) NULL) {
		restore(ps);
		return( (WORD *)SYSERR);
	}
	nbytes = (unsigned int) roundmb(nbytes);
	//Round to the blocks that are allocated by the OS

	for (q= &memlist,p=memlist.mnext ;   p != (struct mblock *) NULL ;    q=p,p=p->mnext)
		//search entire memlist.. to find.. appropriate sized block


		if ( p->mlen == nbytes) { //if you find appropriate block return the block
			q->mnext = p->mnext;
			restore(ps);
			return( (WORD *)p );
		}
		else if ( p->mlen > nbytes ) {  //if the block is bigger than what is needed... cut what is required from it.. and return the required..
			leftover = (struct mblock *)( (unsigned)p + nbytes ); //address of place.. nbytes from p's location...
			q->mnext = leftover;    //previous i.e. q points to the location which nbtyes farther... which is leftOver
			leftover->mnext = p->mnext;   // leftover->next  points to the one.. which initially p->next was pointing to
			leftover->mlen = p->mlen - nbytes;  // lessen the size which originally p said it had
			restore(ps);
			return( (WORD *)p );  //return p
		}

	restore(ps);
	return( (WORD *)SYSERR );
}
